package model;

import java.io.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;


/**
 * Utility Class for searching for strings within an XML Document and outputting
 * an
 * XML Document to the console in String format.
 * Reusable outside the GEDIVA project.
 * 
 * @author Zachary Hopping
 * 
 */
public class XMLUtility {
    /**
     * Document representation of the provided XML document to be operated upon.
     */
    private Document myDoc;
    
    /**
     * String name of file to be operated upon.  Used to display file information to user.
     */
    private String myFileName;

    private static final String PARSE_ERROR = "Error parsing the document";
    private static final String FILE_NOT_FOUND_ERROR = "Error: file not found";
    private static final String TRANSFORM_FAIL_ERROR = "Error: could not transform to String";

    /**
     * Constructor for XMLUtility. Takes a filename and generates a Document
     * 
     * @param fileName is the name of the XML file to be operated upon
     */
    public XMLUtility (String fileName) {
        myFileName = fileName;

        File file = new File(fileName);
        if (file.exists()) {
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            try {
                DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                myDoc = dBuilder.parse(file);
            }
            catch (Exception e) {
                throw new ModelException(PARSE_ERROR, e);
            }
        }
        else {
            throw new ModelException(FILE_NOT_FOUND_ERROR, fileName);
        }
    }

    /**
     * Takes the file name of an XML document and a search string from the
     * console
     * and outputs the number of occurrences of the string in the console.
     */
    public void searchXML () {
        try {
            BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

            System.out.print("Enter search string: ");
            String ele = bf.readLine();
            NodeList list = myDoc.getElementsByTagName(ele);
            if (list.getLength() == 0) {
                System.out.println("Element doesn't exist in the " + myFileName + " Document.");
            }
            else {
                System.out.println("Element occurrs " + list.getLength() + " times in the " +
                                   myFileName);
            }
        }
        catch (Exception e) {
            e.getMessage();
        }
    }
    
    /**
     * Prints the XML document to the console as a String.
     */
    public void printDocumentToConsole () {
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

            StringWriter writer = new StringWriter();
            transformer.transform(new DOMSource(myDoc), new StreamResult(writer));
            String output = writer.getBuffer().toString().replaceAll("\n|\r", "");
            System.out.println(output);
        }
        catch (Exception e) {
            System.out.println(TRANSFORM_FAIL_ERROR);
            e.printStackTrace();
        }
    }
}
